package engine

import (
	"fmt"
	pb "proto"
	"sort"
)

type BattleEngine struct {
	player1   *pb.Player
	player2   *pb.Player
	heroes1   map[int]Hero
	heroes2   map[int]Hero
	roundNum  int
	maxRounds int
}

func NewBattleEngine(p1, p2 *pb.Player) *BattleEngine {
	engine := &BattleEngine{
		player1:   p1,
		player2:   p2,
		heroes1:   make(map[int]Hero),
		heroes2:   make(map[int]Hero),
		maxRounds: 10, // 最大回合数
	}

	// 初始化英雄数据
	engine.initHeroes()

	return engine
}

func (e *BattleEngine) Execute() *pb.BattleResult {
	var rounds []*pb.RoundInfo

	// 执行战斗回合
	for e.roundNum < e.maxRounds {
		e.roundNum++

		// 执行一个回合
		roundInfo := e.executeRound()
		rounds = append(rounds, roundInfo)

		// 检查是否有一方全部阵亡
		if e.checkBattleEnd() {
			break
		}
	}

	// 确定获胜者
	winnerID := e.determineWinner()

	return &pb.BattleResult{
		WinnerId:    winnerID,
		Rounds:      rounds,
		TotalRounds: int32(e.roundNum),
	}
}

func (e *BattleEngine) executeRound() *pb.RoundInfo {
	var actions []*pb.ActionInfo

	// 根据速度排序所有存活的英雄
	heroes := e.getAliveHeroes()

	// 每个英雄依次行动
	for _, hero := range heroes {
		action := e.executeAction(hero)
		if action != nil {
			actions = append(actions, action)
		}
	}

	return &pb.RoundInfo{
		Round:   int32(e.roundNum),
		Actions: actions,
	}
}

func (e *BattleEngine) initHeroes() {
	// 初始化玩家1的英雄
	for _, pos := range e.player1.Formation {
		hero := createHero(pos.HeroId, pos.Position)
		e.heroes1[int(pos.Position)] = hero
	}

	// 初始化玩家2的英雄
	for _, pos := range e.player2.Formation {
		hero := createHero(pos.HeroId, pos.Position)
		e.heroes2[int(pos.Position)] = hero
	}
}

func (e *BattleEngine) getAliveHeroes() []Hero {
	var heroes []Hero

	// 收集所有存活的英雄
	for _, hero := range e.heroes1 {
		if hero.HP > 0 {
			heroes = append(heroes, hero)
		}
	}
	for _, hero := range e.heroes2 {
		if hero.HP > 0 {
			heroes = append(heroes, hero)
		}
	}

	// 根据速度排序
	sort.Slice(heroes, func(i, j int) bool {
		return heroes[i].Speed > heroes[j].Speed
	})

	return heroes
}

func (e *BattleEngine) executeAction(hero Hero) *pb.ActionInfo {
	// 更新技能冷却
	hero.updateCoolDowns()
	// 更新buff

	// 选择目标
	target := e.selectTarget(hero)
	if target == nil {
		return nil
	}

	var action *pb.ActionInfo

	// 检查是否可以使用技能
	if hero.canUseSkill() {
		skill := hero.getAvailableSkill()
		action = e.executeSkill(hero, target, skill)
	} else {
		action = e.executeAttack(hero, target)
	}
	// 再次更新buff,回合结束

	return action
}

func (e *BattleEngine) executeSkill(hero Hero, target *Hero, skill *Skill) *pb.ActionInfo {
	// 造成伤害
	target.HP -= skill.Damage

	// 设置技能冷却
	skill.Current = skill.CoolDown

	return &pb.ActionInfo{
		ActorId:    formatHeroID(hero.ID),
		TargetId:   formatHeroID(target.ID),
		ActionType: "skill",
		Damage:     int32(skill.Damage),
	}
}

func (e *BattleEngine) executeAttack(hero Hero, target *Hero) *pb.ActionInfo {
	// 造成伤害
	damage := hero.Attack
	target.HP -= damage

	return &pb.ActionInfo{
		ActorId:    formatHeroID(hero.ID),
		TargetId:   formatHeroID(target.ID),
		ActionType: "attack",
		Damage:     int32(damage),
	}
}

func (e *BattleEngine) selectTarget(hero Hero) *Hero {
	// 判断英雄属于哪方
	isPlayer1Hero := false
	for _, h := range e.heroes1 {
		if h.ID == hero.ID {
			isPlayer1Hero = true
			break
		}
	}

	// 选择对方存活的英雄作为目标
	targetHeroes := e.heroes2
	if !isPlayer1Hero {
		targetHeroes = e.heroes1
	}

	// 选择第一个存活的英雄作为目标
	for _, target := range targetHeroes {
		if target.HP > 0 {
			return &target
		}
	}

	return nil
}

func (e *BattleEngine) checkBattleEnd() bool {
	return e.allHeroesDead(e.heroes1) || e.allHeroesDead(e.heroes2)
}

func (e *BattleEngine) allHeroesDead(heroes map[int]Hero) bool {
	for _, hero := range heroes {
		if hero.HP > 0 {
			return false
		}
	}
	return true
}

func (e *BattleEngine) determineWinner() string {
	if e.allHeroesDead(e.heroes1) {
		return e.player2.PlayerId
	}
	if e.allHeroesDead(e.heroes2) {
		return e.player1.PlayerId
	}
	return "" // 平局
}

func formatHeroID(id int32) string {
	return fmt.Sprintf("hero_%d", id)
}

func createHero(heroID int32, position int32) Hero {
	// TODO: 从配置或数据库中读取英雄基础属性
	return Hero{
		ID:       heroID,
		Position: position,
		HP:       1000,
		Attack:   100,
		Speed:    10 + int(position), // 临时：根据位置设置速度
		Skills: []Skill{
			{
				ID:       1,
				Name:     "强力一击",
				Damage:   200,
				CoolDown: 3,
			},
		},
	}
}
